DrawBoard();
FillSquare();
ClearSquare();
FillRandomSquare();
ProcessMove();
ProcessRowCol();
IsGameOver();
ClearGameOver();
ResetBoard();
UpdateScore();
UpdateHighScore();
UpdateHighTile();
IntToString();
DigitToChar();

colorList;
boardValues;
score;
hightile;
highgametile;
highscore;

EXPORT PRIME2048()
//2048 v1.3
//2022
//Tony Gallo
//tgallo@tbaytel.com
//http://my.tbaytel.net/tgallo/hp prime
BEGIN

local done;
local key;

//title screen
RECT_P(0,0,319,239,0,RGB(0,0,0));
TEXTOUT_P("2048",145,90,2,RGB(255,0,0));
TEXTOUT_P("v1.3   2022",133,110,1,RGB(255,0,0));
TEXTOUT_P("by Tony Gallo",128,130,1,RGB(255,0,0));
wait(1.5);

colorList:= {
  RGB(255,0,0),RGB(0,255,0),RGB(0,0,255),RGB(255,255,0),RGB(255,0,255),RGB(0,255,255),
  RGB(255,153,153),RGB(153,153,255),
  RGB(0,127,127),RGB(127,127,0),RGB(127,127,127),RGB(127,0,127),RGB(127,0,0)
 };

//clear screen
RECT_P(0,0,319,239,0,RGB(255,255,255));

//credits
TEXTOUT_P("2048",10,5,2,RGB(0,0,0));
TEXTOUT_P("v1.3   2022",100,6,1,RGB(0,0,0));
TEXTOUT_P("by Tony Gallo",250,5,1,RGB(0,0,0));

//sidebar
TEXTOUT_P("Score:",220,70,2,RGB(0,0,0));
TEXTOUT_P("0",225,85,2,RGB(255,0,0));
TEXTOUT_P("High Tile:",220,110,2,RGB(0,0,0));
//TEXTOUT_P("0",225,125,2,RGB(255,0,0));
TEXTOUT_P("High Score:",220,150,2,RGB(0,0,0));
//TEXTOUT_P("0",225,165,2,RGB(255,0,0));

boardValues := makelist(0,A,1,16); //set all value to 0

done:= 0;
WHILE (done==0) DO

score:= 0;
highscore = 0;
highgametile:= 0;
hightile = 0;

UpdateScore(0);

DrawBoard();

WHILE ISKEYDOWN(4)<>1 do

      if IsGameOver()==1 then
         key:=-1;
         while key<>28 and key<>42 and key<>4 do
           wait(.1);
           key:=getkey;
         end;
         
         if key==28 or key==4 then
           done:=1;
         end;
         
         if key==42 then
           ResetBoard();
         end;

         break;
      end;


     wait(.01);
     key:=-1;

     key:=getkey;

     if key==2 or key==7 or key==8 or key==12 then
        ProcessMove(key);
        FillRandomSquare();
     end;
END;

if key==4 then
//pressed ESC to exit
  done:=1;
end;

ClearGameOver();
END;

END;


DrawBoard()
begin
local I;

RECT_P(10,20,210,220,0,RGB(255,255,255));

FOR I FROM 0 to 3 DO
  LINE_P(10+50*I,20,10+50*I,220,RGB(0,0,0));
  LINE_P(10,20+50*I,210,20+50*I,RGB(0,0,0));
END;

FillRandomSquare();
FillRandomSquare();

end;


ResetBoard()
begin
local I;

FOR I FROM 1 TO 16 DO
   boardValues[I]:=0;
END;

FillRandomSquare();
FillRandomSquare();

end;


FillSquare(indx, val)
begin
local I,J;
local color;
local strval;
local strvallen,offset;

FOR I FROM 1 to 13 DO 
  if val == 2^I then
    color := colorList(I);
  end;
END;


   I := irem(indx-1,4);
   J := iquo(indx-1,4);

   RECT_P(11+50*I,21+50*J,59+50*I,69+50*J,color,color);

   strval := IntToString(val);
   strvallen := size(strval);
   CASE
      if strvallen == 1 then
  offset := 18;
      end;

      if strvallen == 2 then
  offset := 12;
      end;

      if strvallen == 3 then
  offset := 6;
      end;

      if strvallen == 4 then
  offset := 1;
      end;
   END;

   TEXTOUT_P(IntToString(val),11+50*I+offset,31+50*J,7,RGB(0,0,0));

   boardValues(indx) := val;
end;


ClearSquare(indx)
begin
local I,J;

   I := irem(indx-1,4);
   J := iquo(indx-1,4);

   RECT_P(11+50*I,21+50*J,59+50*I,69+50*J,RGB(255,255,255),RGB(255,255,255));
   boardValues(indx) <= 0;
end;


FillRandomSquare()
begin
local randnum,val,done;

  randnum := RANDINT(1,10);

  if randnum <= 9 then
      val:=2;
  else
      val:=4;
  end;

  done:=0;
  WHILE (done==0) DO
     randnum := RANDINT(1,16);

     if boardValues(randnum)==0 then
        FillSquare(randnum, val);
        boardValues(randnum):=val;
        done:=1;
     end;
  END;

end;


ProcessMove(key)
begin
local I,J,K;
local rowcol := makelist(0,A,1,4);

   CASE
      //UP
      if key == 2 then
        FOR I FROM 1 TO 4 DO
    J:=I;
    FOR K FROM 1 TO 4 DO
         rowcol[K] := boardValues[J];
         J := J+4;
    END;

    rowcol := ProcessRowCol(rowcol);

  J:=I;

    FOR K FROM 1 TO 4 DO
         boardValues[J] := rowcol[K];

         if rowcol[K] <> 0 then
            FillSquare(J, rowcol[K]);
         else
            ClearSquare(J);
              end;

         J := J+4;

    END;

        END;
      end;

      //LEFT   
      if key == 7 then
        FOR I FROM 1 TO 4 DO
    J:=((I-1)*4)+1;
    FOR K FROM 1 TO 4 DO
         rowcol[K] := boardValues[J];
         J := J+1;
    END;

    rowcol := ProcessRowCol(rowcol);

  J:=((I-1)*4)+1;

    FOR K FROM 1 TO 4 DO
         boardValues[J] := rowcol[K];

         if rowcol[K] <> 0 then
            FillSquare(J, rowcol[K]);
         else
            ClearSquare(J);
              end;

         J := J+1;

    END;

        END;
      end;

      //RIGHT
      if key == 8 then
        FOR I FROM 1 TO 4 DO
    J:=I*4;
    FOR K FROM 1 TO 4 DO


         rowcol[K] := boardValues[J];
         J := J-1;
    END;

    rowcol := ProcessRowCol(rowcol);

  J:=I*4;

    FOR K FROM 1 TO 4 DO
         boardValues[J] := rowcol[K];

         if rowcol[K] <> 0 then
            FillSquare(J, rowcol[K]);
         else
            ClearSquare(J);
              end;

         J := J-1;

    END;

        END;
      end;

      //DOWN
      if key == 12 then
        FOR I FROM 13 TO 16 DO
    J:=I;
    FOR K FROM 1 TO 4 DO
         rowcol[K] := boardValues[J];
         J := J-4;
    END;

    rowcol := ProcessRowCol(rowcol);

  J:=I;

    FOR K FROM 1 TO 4 DO
         boardValues[J] := rowcol[K];

         if rowcol[K] <> 0 then
            FillSquare(J, rowcol[K]);
         else
            ClearSquare(J);
              end;

         J := J-4;

    END;

        END;

      end;
   END;
end;

ProcessRowCol(array)
begin
local I,J;
local processedarray;

processedarray := makelist(0,A,1,4);

J:=1;
FOR I FROM 1 TO 4 DO
  if array[I] <> 0 then
     processedarray[J] := array[I];
     J := J+1;
  end;
END;

FOR I FROM 1 TO 3 DO
   if processedarray[I] == processedarray[I+1] then
      processedarray[I] := processedarray[I]*2;
      processedarray[I+1] := 0;
      UpdateScore(processedarray[I]);
      if processedarray[I] > highgametile then
         highgametile := processedarray[I]
      end;
   end;
END;

FOR I FROM 1 TO 4 DO
   array[I] := 0
END;

J:=1;
FOR I FROM 1 TO 4 DO
  if processedarray[I] <> 0 then
     array[J] := processedarray[I];
     J := J+1;
  end;
END;

return array;
end;


IsGameOver()
begin
local I, gameover;

gameover:=1;

FOR I FROM 1 TO 16 DO
   if boardValues[I] == 0 then
       gameover:=0;
   end;
END;

 if gameover == 1 then
    wait(0.5); //needed to make sure High Score and High Tile get updated
    UpdateHighScore();
    UpdateHighTile();
    TEXTOUT_P("GAME OVER",225,190,2,RGB(0,0,0));
    TEXTOUT_P("Play Again Y/N",220,205,2,RGB(0,0,0));
    return 1;
 else
    return 0;
 end;
end;


ClearGameOver()
begin
  RECT_P(220,190,300,230,RGB(255,255,255),RGB(255,255,255));
end;


UpdateScore(moveVal)
begin
   score := score + moveVal;
   RECT_P(220,83,270,98,RGB(255,255,255),RGB(255,255,255));
   TEXTOUT_P(IntToString(score),225,85,2,RGB(255,0,0));
end;


UpdateHighScore()
begin
   if score > highscore then
     highscore:=score;
     RECT_P(220,163,270,178,RGB(255,255,255),RGB(255,255,255));
     TEXTOUT_P(IntToString(highscore),225,165,2,RGB(255,0,0));
   end;
end;


UpdateHighTile()
begin
   if highgametile > hightile then
     hightile:= highgametile;
     RECT_P(220,123,270,138,RGB(255,255,255),RGB(255,255,255));
     TEXTOUT_P(IntToString(highgametile),225,125,2,RGB(255,0,0));
   end;
end;


IntToString(integer)
begin
local rem;
local string = "";
local negative = 0;

if integer == 0 then
   return "0";
end;

if integer < 0 then
   negative := 1;
  integer := integer * (-1);
end;

while integer > 0 do
  rem := irem(integer,10);
  string := DigitToChar(rem) + string ;
  integer := (integer - rem)/10;
end;

if negative == 1 then
  string:= "-" + string;
end;
return string;

end;


DigitToChar(digit)
begin

if digit == 0 then
  return "0";
end;

if digit == 1 then
  return "1";
end;

if digit == 2 then
  return "2";
end;

if digit == 3 then
  return "3";
end;

if digit == 4 then
  return "4";
end;

if digit == 5 then
  return "5";
end;

if digit == 6 then
  return "6";
end;

if digit == 7 then
  return "7";
end;

if digit == 8 then
  return "8";
end;

if digit == 9 then
  return "9";
end;

end;